<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> this指向讷 </title>
</head>
<body>
    
</body>
</html>
<script>
/*
    什么是this？
        作用域内部使用的关键字，不看函数定义，只看函数的调用方式（箭头函数除外）
        this的指向在函数定义的时候是确定不了的，只有函数执行的时候才能确定this到底指向谁，实际上this的最终指向的是那个调用它的对象

    1.全局调用      函数名()  this => window
	2.对象调用      对象.函数名()  this=>点前面的那个对象
	3.定时器处理函数this => window
	4.事件处理函数  this => 事件原 （谁身上的事件）
	5.自执行函数    this => window
	6.箭头函数      无this ，他的this是上下文。也就是外部作用局的 this
    7.构造函数      this =>  当前实例对象
*/


// 1.全局环境中this指向全局变量（window）this一旦绑定，就不会被任何代码更改。

// 2.对this来说，new的优先级是最高的，如果let c=new foo(),那么foo()里的this就都会绑定在c上。

// 3.call、apply、bind改变this，优先级仅次于new。

// 4.箭头函数的this取决于它外面第一个不是箭头函数的函数的this。

// 5.函数中的this，由调用函数的方式来决定（1）如果函数是独立调用的，在严格模式下（use strict）是指向undefined的，
//   在非严格模式下，指向window（2）如果这个函数是被某一个对象调用，那么this指向被调用的对象；


// this 是执行上下文中的一个属性，它指向最后一次调用这个方法的对象。

// 在实际开发中，this 的指向可以通过四种调用模式来判断。
    // 第一种是函数调用模式，   当一个函数不是一个对象的属性时，直接作为函数来调用时，this 指向全局对象
    // 第二种是方法调用模式，   当一个函数作为一个对象的方法来调用时，this 指向这个对象。
    // 第三种是构造器调用模式， 如果一个函数用new调用时，函数执行前会新创建一个对象，this指向这个新创建的对象。
    // 第四种是 apply 、 call 和 bind 调用模式，
        //这三个方法都可以显示的指定调用函数的 this 指向。
        // apply 方法接收两个参数：一个是 this 绑定的对象，一个是参数数组。
        // call  方法接收的参数，第一个是 this 绑定的对象，后面的其余参数是传入函数执行的参数。也就是说，在使用 call() 方法时，传递给函数的参数必须逐个列举出来。
        // bind  方法通过传入一个对象，返回一个 this 绑定了传入对象的新函数。这个函数的 this 指向除了使用 new 时会被改变，其他情况下都不会改变。
        
    //1默认绑定   
        /*   即独立函数调用时，this指向全局对象，注意如果使用通过模式那么全局对象无法默认绑定
        this绑定绑定至undifinde并抛出TypeError:this in undefined */ 
    //2隐式绑定 
        /*   当函数作为引用属性被添加到对象中，隐式绑定则会把函数调用中的this绑定到这个上下文对象上*/
    //3显示绑定 
        /*   显示绑定运用apply call方法,在调用函数时绑定this，也就是指定调用的函数的this值*/
    //4new绑定 
        /*   就是使用new操作符的时候的this*/



//示例如下
// 函数中的this指向：
// 注：函数中的this指向，与函数的定义没有关系，只看函数的调用；
//         1.全局调用：this->window
//                 函数名() 
//         2.对象调用：this->点前面是谁就是谁
//                 对象.函数()
                    var obj={
                        name:'小明',
                        fn:function(){
                                console.log(this)//obj
                        }
                    }
                    obj.fn()
//         3.定时器处理函数：this->window   
                    setTimeout/clearInterval(function(){},20);
//         4.事件处理函数 this->事件源(谁身上的事件) 
                    box.事件=function(){}
//         5.自执行函数： this->window
                    (function(a){
                        console.log(this)
                    })(10)
//         6.箭头函数没有this，他的this指向上下文，也就是外部作用域的this 
                    var a=()=>{
                            console.log(this)
                    }
//         7.构造函数的  this->当前实例
                    function Person(name,age){
                            console.log("xxxx",this)   //小红    
                            this.name=name
                    }
                    var p1=new Person('小红',10)



    // https://aqingya.cn/articl/33d7b1fa.html
    //this的指向在函数定义的时候是确定不了的，只有函数执行的时候才能确定this到底指向谁，实际上this的最终指向的是那个调用它的对象
    function a(){
        var user = "阿清";
        console.log(this.user); //undefined 指向了window但是全局的window里面没有user  
        console.log(this);      //Window
    }
    a();  //这里 等同于 window.a() //this最终指向的是调用它的对象



    var o = {
        user:"阿清",
        fn:function(){
            console.log(this.user);  //阿清
        }
    }
    o.fn(); //对象o 调用的fn() o里有user是阿清
    // this指向的是对象o，因为你调用这个fn是通过o.fn()执行的，那自然指向就是对象o，
    // this的指向在函数创建的时候是决定不了的，在调用的时候才能决定，谁调用的就指向谁 即点前面的.XXX


    var o = {
        user:"阿清",
        fn:function(){
            console.log(this.user); //阿清
        }
    }
    window.o.fn();
    //window是js中的全局对象，我们创建的变量实际上是给window添加属性，所以这里可以用window点o对象。


    var o = {
        a:10,
        b:{
            a:12,
            fn:function(){
                console.log(this.a); //12
            }
        }
    }
    o.b.fn();   //在这里直接执行了  
    //对象o点出来的，但是同样this并没有执行它

 /* 情况1：如果一个函数中有this，但是它没有被上一级的对象所调用，那么this指向的就是window，这里需要说明的是在js的严格版中this指向的不是window，
    情况2：如果一个函数中有this，这个函数被上一级的对象所调用，那么this指向的就是上一级的对象。
    情况3：如果一个函数中有this，**==这个函数中包含多个对象，尽管这个函数是被最外层的对象所调用，this指向的也只是它上一级的对象==**  */

    var o = {
        a:10,
        b:{
            a:12,
            fn:function(){
                console.log(this.a); //undefined
                console.log(this);   //window
            }
        }
    }
    var j = o.b.fn;     //这里没有加() 来掉用它 而是赋值j 后再下面调用j()
    j();                //这里等同于 window.j()
    // 虽然函数fn是被对象b所引用，但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window


    function Fn(){
        this.user = "阿清";
    }
    var a = new Fn();
    console.log(a.user); //阿清
    //new关键字可以改变this的指向，将这个this指向对象a

    var obj = new Object()
        obj.name = "常东东"
    var obj2 = obj 
        obj.name = "ccc"
    // obj2 = null
    console.log(obj)
    console.log(obj2)


    


</script>